package com.happle.gcmclient;

import java.util.Date;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ExecutionException;

import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Vibrator;
import android.util.Log;
import android.widget.Toast;

import com.google.android.gcm.GCMBaseIntentService;
import com.happle.gcmclient.backendmanager.BackendManager;
import com.happle.gcmclient.backendmanager.task.SendUnregisterTask;
import com.happle.gcmclient.config.CommonUtilities;
import com.happle.gcmclient.config.Constants;
import com.happle.gcmclient.config.GlobalValue;
import com.happle.gcmclient.managers.MessagesManager;
import com.happle.gcmclient.obj.MessageObj;

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class GCMIntentService extends GCMBaseIntentService {

	protected GCMIntentService self;
	private static final String TAG = "GCMIntentService";
	private String regId = "";
	private boolean isLogin = true;
	private MessagesManager msgManager;
	private SendRegistrationTask registrationTask;
	private SendUnregisterTask unRegisterTask;
	private SharedPreferences sPref;

	public GCMIntentService() {
		super(Constants.SENDER_ID);
		// super ("GCMIntentService");
		Log.d(TAG, "GCMIntentService init");
	}

	@Override
	protected void onError(Context ctx, String sError) {
		// TODO Auto-generated method stub
		Log.d(TAG, "Error: " + sError);
	}

	@Override
	protected void onMessage(Context ctx, Intent intent) {
		Log.d(TAG, "Message Received");

		String onlineStatus = CommonUtilities.getInstance(ctx).pullPreferences(
				ctx, Constants.IS_ONLINE);
		// Only process when stasus "ONLINE"
		if (onlineStatus.equalsIgnoreCase(String.valueOf(Constants.STATUS_ON))) {
            MessageObj MsgObj = new MessageObj();
			self = this;
			if (msgManager == null) {
				msgManager = new MessagesManager(self);
			}
            // GCM Service
            MsgObj = getMessageFromGCM(intent);
            MsgObj = msgManager.addMessage(MsgObj);

			if (intent.getStringExtra(Constants.msg_status_p).equals("0") || intent.getStringExtra(Constants.msg_status_p).equals("-2")) {
				if (intent.getStringExtra(Constants.message_p).equals(
						intent.getStringExtra(Constants.wave_id_p))) {
					msgManager.closeConversation(intent
							.getStringExtra(Constants.wave_id_p));
                    sendGCMIntent(ctx, MsgObj);
                    return;
				}
			}
			// Only show notificaiton for Message not closed
            Log.d("","New message status : " + MsgObj.is_msg_status());
//           if (MsgObj.is_msg_status())
				sendGCMIntent(ctx, MsgObj);
			if (CommonUtilities.getInstance(ctx).checkRunningActivities(ctx,
					Constants.MESSAGE_LIST_ACTIVITY_FULL_PATH)) {
				// check if the MessageListActivity is not active
				// if so to send a new object and generate notification
				if (!MessageListActivity.MAIsRunning) {
					generateNotification(ctx, MsgObj);
					MessageListActivity.HasANewMSG = true;
					MessageListActivity.SentMessage = new MessageObj();
					MessageListActivity.SentMessage = MsgObj;
				}
			} else {
				generateNotification(ctx, MsgObj);
				if (CommonUtilities.getInstance(ctx).checkRunningActivities(
						ctx, Constants.CONVERSATION_LIST_ACTIVITY_FULL_PATH)) {
				}
			}
			if (CommonUtilities.getInstance(self).getSettingVibrate())
				vibrate(ctx);
			if (CommonUtilities.getInstance(self).getSettingSound())
				playSound(self);
		}
	}

	public static void dumpIntent(Intent i) {
		Bundle bundle = i.getExtras();
		if (bundle != null) {
			Set<String> keys = bundle.keySet();
			Iterator<String> it = keys.iterator();
			Log.e("GCMIntent", "Dumping Intent start");
			while (it.hasNext()) {
				String key = it.next();
				Log.e("GCMIntent", "[" + key + "=" + bundle.get(key) + "]");
			}
			Log.e("GCMIntent", "Dumping Intent end");
		}
	}

	private MessageObj getMessageFromGCM(Intent intent) {
		dumpIntent(intent);
		String message = intent.getStringExtra(Constants.message_p);
		String wave_id = intent.getStringExtra(Constants.wave_id_p);
		// Wrong key here : msg_id =>msg_id_local
		String msg_id = intent.getStringExtra(Constants.msg_id_local_p);
		String lng_id = intent.getStringExtra(Constants.lng_id_p);
		if (lng_id == null)
			lng_id = Constants.LANGUAGE_ID;
		// U can init a Date from long value(time interval from 1970)
		// http://www.tutorialspoint.com/java/java_date_time.htm
		Date datetime = new Date();
		try {
			datetime = new Date(Long.parseLong(intent
					.getStringExtra(Constants.datetime_p)));
		} catch (NumberFormatException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		String msg_status = intent.getStringExtra(Constants.msg_status_p);
		MessageObj MsgObj = new MessageObj(msg_id, wave_id, false, message,
				lng_id, datetime, (msg_status.equals("1") ? true : false), 0,
				true, true);
		return MsgObj;
	}

	private void vibrate(Context ctx) {
		Vibrator v = (Vibrator) ctx.getSystemService(Context.VIBRATOR_SERVICE);
		v.vibrate(1000);
	}

	private void playSound(Context ctx) {

		MediaPlayer mPlayer = MediaPlayer.create(this, R.raw.new_message_sound);
		mPlayer.start();
		mPlayer.setLooping(false);
	}

	private void sendGCMIntent(Context ctx, MessageObj MsgObj) {

		Intent broadcastIntent = new Intent();
		broadcastIntent.setAction(Constants.ACTION_ON_NEW_MESSAGE);
		broadcastIntent.putExtra(Constants.KEY_MESSAGE_OBJECT, MsgObj);
		ctx.sendBroadcast(broadcastIntent);
	}

	@Override
	protected void onRegistered(Context ctx, String regId) {
		// savePreverences(Constants.REGISTRATION_ID, regId);
		GlobalValue.registerId = regId;
		int tryToSave = 0;
		do {
			if (CommonUtilities.getInstance(self).savePreverences(ctx,
					CommonUtilities.REGISTRATION_ID, regId))
				tryToSave = 5;
			tryToSave++;
		} while (tryToSave < 5);
		isLogin = false;
		try {
			// send regId to your server
			registrationTask = new SendRegistrationTask(isLogin, regId);
			registrationTask.execute();
			int taskResult = registrationTask.get();
			if (taskResult != -1)
				CommonUtilities.getInstance(self).savePreverences(ctx,
						Constants.IS_ONLINE,
						String.valueOf(Constants.STATUS_ON));
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}
	}

	class SendRegistrationTask extends AsyncTask<Void, Boolean, Integer> {
		private String regId = "";
		private boolean isLogin = true;

		public SendRegistrationTask(Boolean IsLogin, String regId) {
			this.regId = regId;
			this.isLogin = IsLogin;
		}

		@Override
		protected void onPreExecute() {
			super.onPreExecute();
		}

		@Override
		protected Integer doInBackground(Void... params) {
			int error = Constants.FAILED;
			try {
				BackendManager bManager = new BackendManager();
				error = bManager.sendLoginRegistration(regId, isLogin);
			} catch (Exception e) {
				e.printStackTrace();
			}
			Log.d(TAG, String.valueOf(error));
			return error;
		}
	}

	@Override
	protected void onUnregistered(Context ctx, String regId) {
		Log.d("GCMIntent", "Unregisted Push");
		// send notification to your server to remove that regId
		unRegisterTask = new SendUnregisterTask(false, regId);
		unRegisterTask.execute();
		Log.d(TAG, regId);
	}

	@SuppressWarnings("deprecation")
	public static void generateNotification(Context context, MessageObj MsgObj) {
		int icon = R.drawable.ic_launcher;
		long when = System.currentTimeMillis();
		String title = Constants.NOTIF_TITLE;
		NotificationManager nm = (NotificationManager) context
				.getSystemService(Context.NOTIFICATION_SERVICE);
		@SuppressWarnings("deprecation")
		Notification notification = new Notification(icon,
				MsgObj.get_message(), when);
		notification.flags |= Notification.FLAG_AUTO_CANCEL;
		Intent intent = new Intent(context, MessageListActivity.class);
		// Set a unique data uri for each notification to make sure the activity
		// gets updated
		intent.setData(Uri.parse(MsgObj.get_message()));
		// intent.putExtra(Constants.WAVE_ID, MsgObj.get_wave_id());
		intent.putExtra(Constants.KEY_MESSAGE_OBJECT, MsgObj);
		intent.putExtra(Constants.FIELD_REQUEST_CODE,
				String.valueOf(Constants.REQUEST_CODE_NOTIF));
		intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
				| Intent.FLAG_ACTIVITY_CLEAR_TASK);
		PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
				intent, 0);
		notification.setLatestEventInfo(context, title, MsgObj.get_message(),
				pendingIntent);
		nm.notify(R.id.notification_id, notification);
	}

}
